using System;

namespace NetduinoRobot.Common
{
    /// <summary>
    /// Utility Class to filter series of measurements.
    /// FilterType can be set on creation time only - might be changed in future
    /// Written by: Salvador Richter
    /// Appache License Version 2.0 
    /// </summary>
    public class Filter
    {
        public enum FilterType { None, Linear, LowPass, Kalman };

        private FilterType _filterType;
        private int _defaulFilterLength = 5;
        private float[] _filterValues;
        private int _filterIndex = 0;

        public int FilterLength { get { return _defaulFilterLength; } set { _defaulFilterLength = value; _filterValues = new float[_defaulFilterLength]; } }

        /// <summary>
        /// Basic constructor. Creates Filter.FilterType.None
        /// </summary>
        public Filter():this(FilterType.None)
        {
        }

        /// <summary>
        /// Constructor to be used if FilterType !" None is to be used
        /// </summary>
        /// <param name="Type">The type of filter algorithm to be used</param>
        public Filter(FilterType Type)
        {
            _filterValues = new float[_defaulFilterLength];
            _filterType = Type;
        }

        /// <summary>
        /// This method performs data filtering, therefore it stores the given value
        /// </summary>
        /// <param name="value">the value to be filtered</param>
        /// <returns>the filtered value</returns>
        public float DoFiltering(float value)
        {
            // store value to be filtered in array
            _filterValues[_filterIndex] = value;
            // adjust array index
            _filterIndex++;
            if (_filterIndex == _defaulFilterLength)
            {
                _filterIndex = 0;
            }

            // execute filter operation
            switch (_filterType)
            {
                case FilterType.None:
                    return value;
                case FilterType.Linear:
                    return FilterLinear();
                case FilterType.LowPass:
                    throw new NotImplementedException(FilterType.LowPass.ToString());
                case FilterType.Kalman:
                    throw new NotImplementedException(FilterType.Kalman.ToString());
            }
            return value;
        }

        /// <summary>
        /// Implementation of FilterType Linear
        /// </summary>
        /// <returns>filtered value</returns>
        private float FilterLinear()
        {
            float sum = 0;
            // calculate meridian
            foreach (float item in _filterValues)
            {
                sum += item;
            }
            return sum/_defaulFilterLength;
        }
    }
}
